home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume24 / gnucalc / part05 < prev    next >
Encoding:
Text File  |  1991-10-28  |  55.5 KB  |  1,782 lines

  1. Newsgroups: comp.sources.misc
  2. From: daveg@synaptics.com (David Gillespie)
  3. Subject:  v24i053:  gnucalc - GNU Emacs Calculator, v2.00, Part05/56
  4. Message-ID: <1991Oct29.042451.7188@sparky.imd.sterling.com>
  5. X-Md4-Signature: c9449dd13a7867353f1d8e87767c2a9c
  6. Date: Tue, 29 Oct 1991 04:24:51 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: daveg@synaptics.com (David Gillespie)
  10. Posting-number: Volume 24, Issue 53
  11. Archive-name: gnucalc/part05
  12. Environment: Emacs
  13. Supersedes: gmcalc: Volume 13, Issue 27-45
  14.  
  15. ---- Cut Here and unpack ----
  16. #!/bin/sh
  17. # this is Part.05 (part 5 of a multipart archive)
  18. # do not concatenate these parts, unpack them in order with /bin/sh
  19. # file calc-alg-2.el continued
  20. #
  21. if test ! -r _shar_seq_.tmp; then
  22.     echo 'Please unpack part 1 first!'
  23.     exit 1
  24. fi
  25. (read Scheck
  26.  if test "$Scheck" != 5; then
  27.     echo Please unpack part "$Scheck" next!
  28.     exit 1
  29.  else
  30.     exit 0
  31.  fi
  32. ) < _shar_seq_.tmp || exit 1
  33. if test ! -f _shar_wnt_.tmp; then
  34.     echo 'x - still skipping calc-alg-2.el'
  35. else
  36. echo 'x - continuing file calc-alg-2.el'
  37. sed 's/^X//' << 'SHAR_EOF' >> 'calc-alg-2.el' &&
  38. X     (not (math-expr-contains (nth 2 expr) var)))
  39. X    (math-mul (calcFunc-integ (nth 1 expr) var low high) (nth 2 expr)))
  40. X   ((and (eq (car-safe expr) '/)
  41. X     (not (math-expr-contains (nth 1 expr) var))
  42. X     (not (math-equal-int (nth 1 expr) 1)))
  43. X    (math-mul (nth 1 expr)
  44. X          (calcFunc-integ (math-div 1 (nth 2 expr)) var low high)))
  45. X   ((and (eq (car-safe expr) '/)
  46. X     (not (math-expr-contains (nth 2 expr) var)))
  47. X    (math-div (calcFunc-integ (nth 1 expr) var low high) (nth 2 expr)))
  48. X   ((eq (car-safe expr) 'vec)
  49. X    (cons 'vec (mapcar (function (lambda (x) (calcFunc-integ x var low high)))
  50. X               (cdr expr))))
  51. X   (t
  52. X    (let ((state (list calc-angle-mode
  53. X               ;;calc-symbolic-mode
  54. X               ;;calc-prefer-frac
  55. X               calc-internal-prec
  56. X               (calc-var-value 'var-IntegRules)
  57. X               (calc-var-value 'var-IntegSimpRules))))
  58. X      (or (equal state math-integral-cache-state)
  59. X      (setq math-integral-cache-state state
  60. X        math-integral-cache nil)))
  61. X    (let* ((math-max-integral-limit (or (and (boundp 'var-IntegLimit)
  62. X                         (natnump var-IntegLimit)
  63. X                         var-IntegLimit)
  64. X                    3))
  65. X       (math-integral-limit 1)
  66. X       (sexpr (math-expr-subst expr var math-integ-var))
  67. X       (trace-buffer (get-buffer "*Trace*"))
  68. X       (calc-language (if (eq calc-language 'big) nil calc-language))
  69. X       (math-any-substs t)
  70. X       (math-enable-subst nil)
  71. X       (math-prev-parts-v nil)
  72. X       (math-doing-parts nil)
  73. X       (math-good-parts nil)
  74. X       (res
  75. X        (if trace-buffer
  76. X        (let ((calcbuf (current-buffer))
  77. X              (calcwin (selected-window)))
  78. X          (unwind-protect
  79. X              (progn
  80. X            (if (get-buffer-window trace-buffer)
  81. X                (select-window (get-buffer-window trace-buffer)))
  82. X            (set-buffer trace-buffer)
  83. X            (goto-char (point-max))
  84. X            (or (assq 'scroll-stop (buffer-local-variables))
  85. X                (progn
  86. X                  (make-local-variable 'scroll-step)
  87. X                  (setq scroll-step 3)))
  88. X            (insert "\n\n\n")
  89. X            (set-buffer calcbuf)
  90. X            (math-try-integral sexpr))
  91. X            (select-window calcwin)
  92. X              (set-buffer calcbuf)))
  93. X          (math-try-integral sexpr))))
  94. X      (if res
  95. X      (progn
  96. X        (if (calc-has-rules 'var-IntegAfterRules)
  97. X        (setq res (math-rewrite res '(var IntegAfterRules
  98. X                          var-IntegAfterRules))))
  99. X        (math-simplify
  100. X         (if (and low high)
  101. X         (math-sub (math-expr-subst res math-integ-var high)
  102. X               (math-expr-subst res math-integ-var low))
  103. X           (setq res (math-fix-const-terms res math-integ-vars))
  104. X           (if low
  105. X           (math-expr-subst res math-integ-var low)
  106. X         (math-expr-subst res math-integ-var var)))))
  107. X    (append (list 'calcFunc-integ expr var)
  108. X        (and low (list low))
  109. X        (and high (list high)))))))
  110. )
  111. X
  112. X
  113. (math-defintegral calcFunc-inv
  114. X  (math-integral (math-div 1 u)))
  115. X
  116. (math-defintegral calcFunc-conj
  117. X  (let ((int (math-integral u)))
  118. X    (and int
  119. X     (list 'calcFunc-conj int))))
  120. X
  121. (math-defintegral calcFunc-deg
  122. X  (let ((int (math-integral u)))
  123. X    (and int
  124. X     (list 'calcFunc-deg int))))
  125. X
  126. (math-defintegral calcFunc-rad
  127. X  (let ((int (math-integral u)))
  128. X    (and int
  129. X     (list 'calcFunc-rad int))))
  130. X
  131. (math-defintegral calcFunc-re
  132. X  (let ((int (math-integral u)))
  133. X    (and int
  134. X     (list 'calcFunc-re int))))
  135. X
  136. (math-defintegral calcFunc-im
  137. X  (let ((int (math-integral u)))
  138. X    (and int
  139. X     (list 'calcFunc-im int))))
  140. X
  141. (math-defintegral calcFunc-sqrt
  142. X  (and (equal u math-integ-var)
  143. X       (math-mul '(frac 2 3)
  144. X         (list 'calcFunc-sqrt (math-pow u 3)))))
  145. X
  146. (math-defintegral calcFunc-exp
  147. X  (and (equal u math-integ-var)
  148. X       (list 'calcFunc-exp u)))
  149. X
  150. (math-defintegral calcFunc-ln
  151. X  (or (and (equal u math-integ-var)
  152. X       (math-sub (math-mul u (list 'calcFunc-ln u)) u))
  153. X      (and (eq (car u) '*)
  154. X       (math-integral (math-add (list 'calcFunc-ln (nth 1 u))
  155. X                    (list 'calcFunc-ln (nth 2 u)))))
  156. X      (and (eq (car u) '/)
  157. X       (math-integral (math-sub (list 'calcFunc-ln (nth 1 u))
  158. X                    (list 'calcFunc-ln (nth 2 u)))))
  159. X      (and (eq (car u) '^)
  160. X       (math-integral (math-mul (nth 2 u)
  161. X                    (list 'calcFunc-ln (nth 1 u)))))))
  162. X
  163. (math-defintegral calcFunc-log10
  164. X  (and (equal u math-integ-var)
  165. X       (math-sub (math-mul u (list 'calcFunc-ln u))
  166. X         (math-div u (list 'calcFunc-ln 10)))))
  167. X
  168. (math-defintegral-2 calcFunc-log
  169. X  (math-integral (math-div (list 'calcFunc-ln u)
  170. X               (list 'calcFunc-ln v))))
  171. X
  172. (math-defintegral calcFunc-sin
  173. X  (and (equal u math-integ-var)
  174. X       (math-neg (math-from-radians-2 (list 'calcFunc-cos u)))))
  175. X
  176. (math-defintegral calcFunc-cos
  177. X  (and (equal u math-integ-var)
  178. X       (math-from-radians-2 (list 'calcFunc-sin u))))
  179. X
  180. (math-defintegral calcFunc-tan
  181. X  (and (equal u math-integ-var)
  182. X       (math-neg (math-from-radians-2
  183. X          (list 'calcFunc-ln (list 'calcFunc-cos u))))))
  184. X
  185. (math-defintegral calcFunc-arcsin
  186. X  (and (equal u math-integ-var)
  187. X       (math-add (math-mul u (list 'calcFunc-arcsin u))
  188. X         (math-from-radians-2
  189. X          (list 'calcFunc-sqrt (math-sub 1 (math-sqr u)))))))
  190. X
  191. (math-defintegral calcFunc-arccos
  192. X  (and (equal u math-integ-var)
  193. X       (math-sub (math-mul u (list 'calcFunc-arccos u))
  194. X         (math-from-radians-2
  195. X          (list 'calcFunc-sqrt (math-sub 1 (math-sqr u)))))))
  196. X
  197. (math-defintegral calcFunc-arctan
  198. X  (and (equal u math-integ-var)
  199. X       (math-sub (math-mul u (list 'calcFunc-arctan u))
  200. X         (math-from-radians-2
  201. X          (math-div (list 'calcFunc-ln (math-add 1 (math-sqr u)))
  202. X                2)))))
  203. X
  204. (math-defintegral calcFunc-sinh
  205. X  (and (equal u math-integ-var)
  206. X       (list 'calcFunc-cosh u)))
  207. X
  208. (math-defintegral calcFunc-cosh
  209. X  (and (equal u math-integ-var)
  210. X       (list 'calcFunc-sinh u)))
  211. X
  212. (math-defintegral calcFunc-tanh
  213. X  (and (equal u math-integ-var)
  214. X       (list 'calcFunc-ln (list 'calcFunc-cosh u))))
  215. X
  216. (math-defintegral calcFunc-arcsinh
  217. X  (and (equal u math-integ-var)
  218. X       (math-sub (math-mul u (list 'calcFunc-arcsinh u))
  219. X         (list 'calcFunc-sqrt (math-add (math-sqr u) 1)))))
  220. X
  221. (math-defintegral calcFunc-arccosh
  222. X  (and (equal u math-integ-var)
  223. X       (math-sub (math-mul u (list 'calcFunc-arccosh u))
  224. X         (list 'calcFunc-sqrt (math-sub 1 (math-sqr u))))))
  225. X
  226. (math-defintegral calcFunc-arctanh
  227. X  (and (equal u math-integ-var)
  228. X       (math-sub (math-mul u (list 'calcFunc-arctan u))
  229. X         (math-div (list 'calcFunc-ln
  230. X                 (math-add 1 (math-sqr u)))
  231. X               2))))
  232. X
  233. ;;; (Ax + B) / (ax^2 + bx + c)^n forms.
  234. (math-defintegral-2 /
  235. X  (math-integral-rational-funcs u v))
  236. X
  237. (defun math-integral-rational-funcs (u v)
  238. X  (let ((pu (math-is-polynomial u math-integ-var 1))
  239. X    (vpow 1) pv)
  240. X    (and pu
  241. X     (catch 'int-rat
  242. X       (if (and (eq (car-safe v) '^) (natnump (nth 2 v)))
  243. X           (setq vpow (nth 2 v)
  244. X             v (nth 1 v)))
  245. X       (and (setq pv (math-is-polynomial v math-integ-var 2))
  246. X        (let ((int (math-mul-thru
  247. X                (car pu)
  248. X                (math-integral-q02 (car pv) (nth 1 pv)
  249. X                           (nth 2 pv) v vpow))))
  250. X          (if (cdr pu)
  251. X              (setq int (math-add int
  252. X                      (math-mul-thru
  253. X                       (nth 1 pu)
  254. X                       (math-integral-q12
  255. X                        (car pv) (nth 1 pv)
  256. X                        (nth 2 pv) v vpow)))))
  257. X          int))))))
  258. X
  259. (defun math-integral-q12 (a b c v vpow)
  260. X  (let (q)
  261. X    (cond ((not c)
  262. X       (cond ((= vpow 1)
  263. X          (math-sub (math-div math-integ-var b)
  264. X                (math-mul (math-div a (math-sqr b))
  265. X                      (list 'calcFunc-ln v))))
  266. X         ((= vpow 2)
  267. X          (math-div (math-add (list 'calcFunc-ln v)
  268. X                      (math-div a v))
  269. X                (math-sqr b)))
  270. X         (t
  271. X          (let ((nm1 (math-sub vpow 1))
  272. X            (nm2 (math-sub vpow 2)))
  273. X            (math-div (math-sub
  274. X                   (math-div a (math-mul nm1 (math-pow v nm1)))
  275. X                   (math-div 1 (math-mul nm2 (math-pow v nm2))))
  276. X                  (math-sqr b))))))
  277. X      ((math-zerop
  278. X        (setq q (math-sub (math-mul 4 (math-mul a c)) (math-sqr b))))
  279. X       (let ((part (math-div b (math-mul 2 c))))
  280. X         (math-mul-thru (math-pow c vpow)
  281. X                (math-integral-q12 part 1 nil
  282. X                           (math-add math-integ-var part)
  283. X                           (* vpow 2)))))
  284. X      ((= vpow 1)
  285. X       (and (math-ratp q) (math-negp q)
  286. X        (let ((calc-symbolic-mode t))
  287. X          (math-ratp (math-sqrt (math-neg q))))
  288. X        (throw 'int-rat nil))  ; should have used calcFunc-apart first
  289. X       (math-sub (math-div (list 'calcFunc-ln v) (math-mul 2 c))
  290. X             (math-mul-thru (math-div b (math-mul 2 c))
  291. X                    (math-integral-q02 a b c v 1))))
  292. X      (t
  293. X       (let ((n (1- vpow)))
  294. X         (math-sub (math-neg (math-div
  295. X                  (math-add (math-mul b math-integ-var)
  296. X                        (math-mul 2 a))
  297. X                  (math-mul n (math-mul q (math-pow v n)))))
  298. X               (math-mul-thru (math-div (math-mul b (1- (* 2 n)))
  299. X                        (math-mul n q))
  300. X                      (math-integral-q02 a b c v n)))))))
  301. )
  302. X
  303. (defun math-integral-q02 (a b c v vpow)
  304. X  (let (q rq part)
  305. X    (cond ((not c)
  306. X       (cond ((= vpow 1)
  307. X          (math-div (list 'calcFunc-ln v) b))
  308. X         (t
  309. X          (math-div (math-pow v (- 1 vpow))
  310. X                (math-mul (- 1 vpow) b)))))
  311. X      ((math-zerop
  312. X        (setq q (math-sub (math-mul 4 (math-mul a c)) (math-sqr b))))
  313. X       (let ((part (math-div b (math-mul 2 c))))
  314. X         (math-mul-thru (math-pow c vpow)
  315. X                (math-integral-q02 part 1 nil
  316. X                           (math-add math-integ-var part)
  317. X                           (* vpow 2)))))
  318. X      ((progn
  319. X         (setq part (math-add (math-mul 2 (math-mul c math-integ-var)) b))
  320. X         (> vpow 1))
  321. X       (let ((n (1- vpow)))
  322. X         (math-add (math-div part (math-mul n (math-mul q (math-pow v n))))
  323. X               (math-mul-thru (math-div (math-mul (- (* 4 n) 2) c)
  324. X                        (math-mul n q))
  325. X                      (math-integral-q02 a b c v n)))))
  326. X      ((math-guess-if-neg q)
  327. X       (setq rq (list 'calcFunc-sqrt (math-neg q)))
  328. X       ;;(math-div-thru (list 'calcFunc-ln
  329. X       ;;            (math-div (math-sub part rq)
  330. X       ;;                  (math-add part rq)))
  331. X       ;;          rq)
  332. X       (math-div (math-mul -2 (list 'calcFunc-arctanh
  333. X                    (math-div part rq)))
  334. X             rq))
  335. X      (t
  336. X       (setq rq (list 'calcFunc-sqrt q))
  337. X       (math-div (math-mul 2 (math-to-radians-2
  338. X                  (list 'calcFunc-arctan
  339. X                    (math-div part rq))))
  340. X             rq))))
  341. )
  342. X
  343. X
  344. X
  345. X
  346. (defun calcFunc-table (expr var &optional low high step)
  347. X  (or low (setq low '(neg (var inf var-inf)) high '(var inf var-inf)))
  348. X  (or high (setq high low low 1))
  349. X  (and (or (math-infinitep low) (math-infinitep high))
  350. X       (not step)
  351. X       (math-scan-for-limits expr))
  352. X  (and step (math-zerop step) (math-reject-arg step 'nonzerop))
  353. X  (let ((known (+ (if (Math-objectp low) 1 0)
  354. X          (if (Math-objectp high) 1 0)
  355. X          (if (or (null step) (Math-objectp step)) 1 0)))
  356. X    (count '(var inf var-inf))
  357. X    vec)
  358. X    (or (= known 2)   ; handy optimization
  359. X    (equal high '(var inf var-inf))
  360. X    (progn
  361. X      (setq count (math-div (math-sub high low) (or step 1)))
  362. X      (or (Math-objectp count)
  363. X          (setq count (math-simplify count)))
  364. X      (if (Math-messy-integerp count)
  365. X          (setq count (math-trunc count)))))
  366. X    (if (Math-negp count)
  367. X    (setq count -1))
  368. X    (if (integerp count)
  369. X    (let ((var-DUMMY nil)
  370. X          (vec math-tabulate-initial)
  371. X          (math-working-step-2 (1+ count))
  372. X          (math-working-step 0))
  373. X      (setq expr (math-evaluate-expr
  374. X              (math-expr-subst expr var '(var DUMMY var-DUMMY))))
  375. X      (while (>= count 0)
  376. X        (setq math-working-step (1+ math-working-step)
  377. X          var-DUMMY low
  378. X          vec (cond ((eq math-tabulate-function 'calcFunc-sum)
  379. X                 (math-add vec (math-evaluate-expr expr)))
  380. X                ((eq math-tabulate-function 'calcFunc-prod)
  381. X                 (math-mul vec (math-evaluate-expr expr)))
  382. X                (t
  383. X                 (cons (math-evaluate-expr expr) vec)))
  384. X          low (math-add low (or step 1))
  385. X          count (1- count)))
  386. X      (if math-tabulate-function
  387. X          vec
  388. X        (cons 'vec (nreverse vec))))
  389. X      (if (Math-integerp count)
  390. X      (calc-record-why 'fixnump high)
  391. X    (if (Math-num-integerp low)
  392. X        (if (Math-num-integerp high)
  393. X        (calc-record-why 'integerp step)
  394. X          (calc-record-why 'integerp high))
  395. X      (calc-record-why 'integerp low)))
  396. X      (append (list (or math-tabulate-function 'calcFunc-table)
  397. X            expr var)
  398. X          (and (not (and (equal low '(neg (var inf var-inf)))
  399. X                 (equal high '(var inf var-inf))))
  400. X           (list low high))
  401. X          (and step (list step)))))
  402. )
  403. X
  404. (setq math-tabulate-initial nil)
  405. (setq math-tabulate-function nil)
  406. X
  407. (defun math-scan-for-limits (x)
  408. X  (cond ((Math-primp x))
  409. X    ((and (eq (car x) 'calcFunc-subscr)
  410. X          (Math-vectorp (nth 1 x))
  411. X          (math-expr-contains (nth 2 x) var))
  412. X     (let* ((calc-next-why nil)
  413. X        (low-val (math-solve-for (nth 2 x) 1 var nil))
  414. X        (high-val (math-solve-for (nth 2 x) (1- (length (nth 1 x)))
  415. X                      var nil))
  416. X        temp)
  417. X       (and low-val (math-realp low-val)
  418. X        high-val (math-realp high-val))
  419. X       (and (Math-lessp high-val low-val)
  420. X        (setq temp low-val low-val high-val high-val temp))
  421. X       (setq low (math-max low (math-ceiling low-val))
  422. X         high (math-min high (math-floor high-val)))))
  423. X    (t
  424. X     (while (setq x (cdr x))
  425. X       (math-scan-for-limits (car x)))))
  426. )
  427. X
  428. X
  429. (defun calcFunc-sum (expr var &optional low high step)
  430. X  (if math-disable-sums (math-reject-arg))
  431. X  (let* ((res (let* ((calc-internal-prec (+ calc-internal-prec 2)))
  432. X        (math-sum-rec expr var low high step)))
  433. X     (math-disable-sums t))
  434. X    (math-normalize res))
  435. )
  436. (setq math-disable-sums nil)
  437. X
  438. (defun math-sum-rec (expr var &optional low high step)
  439. X  (or low (setq low '(neg (var inf var-inf)) high '(var inf var-inf)))
  440. X  (and low (not high) (setq high low low 1))
  441. X  (let (t1 t2 val)
  442. X    (setq val
  443. X      (cond
  444. X       ((not (math-expr-contains expr var))
  445. X        (math-mul expr (math-add (math-div (math-sub high low) (or step 1))
  446. X                     1)))
  447. X       ((and step (not (math-equal-int step 1)))
  448. X        (if (math-negp step)
  449. X        (math-sum-rec expr var high low (math-neg step))
  450. X          (let ((lo (math-simplify (math-div low step))))
  451. X        (if (math-known-num-integerp lo)
  452. X            (math-sum-rec (math-normalize
  453. X                   (math-expr-subst expr var
  454. X                            (math-mul step var)))
  455. X                  var lo (math-simplify (math-div high step)))
  456. X          (math-sum-rec (math-normalize
  457. X                 (math-expr-subst expr var
  458. X                          (math-add (math-mul step var)
  459. X                                low)))
  460. X                var 0
  461. X                (math-simplify (math-div (math-sub high low)
  462. X                             step)))))))
  463. X       ((memq (setq t1 (math-compare low high)) '(0 1))
  464. X        (if (eq t1 0)
  465. X        (math-expr-subst expr var low)
  466. X          0))
  467. X       ((setq t1 (math-is-polynomial expr var 20))
  468. X        (let ((poly nil)
  469. X          (n 0))
  470. X          (while t1
  471. X        (setq poly (math-poly-mix poly 1
  472. X                      (math-sum-integer-power n) (car t1))
  473. X              n (1+ n)
  474. X              t1 (cdr t1)))
  475. X          (setq n (math-build-polynomial-expr poly high))
  476. X          (if (memq low '(0 1))
  477. X          n
  478. X        (math-sub n (math-build-polynomial-expr poly
  479. X                            (math-sub low 1))))))
  480. X       ((and (memq (car expr) '(+ -))
  481. X         (setq t1 (math-sum-rec (nth 1 expr) var low high)
  482. X               t2 (math-sum-rec (nth 2 expr) var low high))
  483. X         (not (and (math-expr-calls t1 '(calcFunc-sum))
  484. X               (math-expr-calls t2 '(calcFunc-sum)))))
  485. X        (list (car expr) t1 t2))
  486. X       ((and (eq (car expr) '*)
  487. X         (setq t1 (math-sum-const-factors expr var)))
  488. X        (math-mul (car t1) (math-sum-rec (cdr t1) var low high)))
  489. X       ((and (eq (car expr) '*) (memq (car-safe (nth 1 expr)) '(+ -)))
  490. X        (math-sum-rec (math-add-or-sub (math-mul (nth 1 (nth 1 expr))
  491. X                             (nth 2 expr))
  492. X                       (math-mul (nth 2 (nth 1 expr))
  493. X                             (nth 2 expr))
  494. X                       nil (eq (car (nth 1 expr)) '-))
  495. X              var low high))
  496. X       ((and (eq (car expr) '*) (memq (car-safe (nth 2 expr)) '(+ -)))
  497. X        (math-sum-rec (math-add-or-sub (math-mul (nth 1 expr)
  498. X                             (nth 1 (nth 2 expr)))
  499. X                       (math-mul (nth 1 expr)
  500. X                             (nth 2 (nth 2 expr)))
  501. X                       nil (eq (car (nth 2 expr)) '-))
  502. X              var low high))
  503. X       ((and (eq (car expr) '/)
  504. X         (not (math-primp (nth 1 expr)))
  505. X         (setq t1 (math-sum-const-factors (nth 1 expr) var)))
  506. X        (math-mul (car t1)
  507. X              (math-sum-rec (math-div (cdr t1) (nth 2 expr))
  508. X                    var low high)))
  509. X       ((and (eq (car expr) '/)
  510. X         (setq t1 (math-sum-const-factors (nth 2 expr) var)))
  511. X        (math-div (math-sum-rec (math-div (nth 1 expr) (cdr t1))
  512. X                    var low high)
  513. X              (car t1)))
  514. X       ((eq (car expr) 'neg)
  515. X        (math-neg (math-sum-rec (nth 1 expr) var low high)))
  516. X       ((and (eq (car expr) '^)
  517. X         (not (math-expr-contains (nth 1 expr) var))
  518. X         (setq t1 (math-is-polynomial (nth 2 expr) var 1)))
  519. X        (let ((x (math-pow (nth 1 expr) (nth 1 t1))))
  520. X          (math-div (math-mul (math-sub (math-pow x (math-add 1 high))
  521. X                        (math-pow x low))
  522. X                  (math-pow (nth 1 expr) (car t1)))
  523. X            (math-sub x 1))))
  524. X       ((and (setq t1 (math-to-exponentials expr))
  525. X         (setq t1 (math-sum-rec t1 var low high))
  526. X         (not (math-expr-calls t1 '(calcFunc-sum))))
  527. X        (math-to-exps t1))
  528. X       ((memq (car expr) '(calcFunc-ln calcFunc-log10))
  529. X        (list (car expr) (calcFunc-prod (nth 1 expr) var low high)))
  530. X       ((and (eq (car expr) 'calcFunc-log)
  531. X         (= (length expr) 3)
  532. X         (not (math-expr-contains (nth 2 expr) var)))
  533. X        (list 'calcFunc-log
  534. X          (calcFunc-prod (nth 1 expr) var low high)
  535. X          (nth 2 expr)))))
  536. X    (if (equal val '(var nan var-nan)) (setq val nil))
  537. X    (or val
  538. X    (let* ((math-tabulate-initial 0)
  539. X           (math-tabulate-function 'calcFunc-sum))
  540. X      (calcFunc-table expr var low high))))
  541. )
  542. X
  543. (defun calcFunc-asum (expr var low &optional high step no-mul-flag)
  544. X  (or high (setq high low low 1))
  545. X  (if (and step (not (math-equal-int step 1)))
  546. X      (if (math-negp step)
  547. X      (math-mul (math-pow -1 low)
  548. X            (calcFunc-asum expr var high low (math-neg step) t))
  549. X    (let ((lo (math-simplify (math-div low step))))
  550. X      (if (math-num-integerp lo)
  551. X          (calcFunc-asum (math-normalize
  552. X                  (math-expr-subst expr var
  553. X                           (math-mul step var)))
  554. X                 var lo (math-simplify (math-div high step)))
  555. X        (calcFunc-asum (math-normalize
  556. X                (math-expr-subst expr var
  557. X                         (math-add (math-mul step var)
  558. X                               low)))
  559. X               var 0
  560. X               (math-simplify (math-div (math-sub high low)
  561. X                            step))))))
  562. X    (math-mul (if no-mul-flag 1 (math-pow -1 low))
  563. X          (calcFunc-sum (math-mul (math-pow -1 var) expr) var low high)))
  564. )
  565. X
  566. (defun math-sum-const-factors (expr var)
  567. X  (let ((const nil)
  568. X    (not-const nil)
  569. X    (p expr))
  570. X    (while (eq (car-safe p) '*)
  571. X      (if (math-expr-contains (nth 1 p) var)
  572. X      (setq not-const (cons (nth 1 p) not-const))
  573. X    (setq const (cons (nth 1 p) const)))
  574. X      (setq p (nth 2 p)))
  575. X    (if (math-expr-contains p var)
  576. X    (setq not-const (cons p not-const))
  577. X      (setq const (cons p const)))
  578. X    (and const
  579. X     (cons (let ((temp (car const)))
  580. X         (while (setq const (cdr const))
  581. X           (setq temp (list '* (car const) temp)))
  582. X         temp)
  583. X           (let ((temp (or (car not-const) 1)))
  584. X         (while (setq not-const (cdr not-const))
  585. X           (setq temp (list '* (car not-const) temp)))
  586. X         temp))))
  587. )
  588. X
  589. ;; Following is from CRC Math Tables, 27th ed, pp. 52-53.
  590. (defun math-sum-integer-power (pow)
  591. X  (let ((calc-prefer-frac t)
  592. X    (n (length math-sum-int-pow-cache)))
  593. X    (while (<= n pow)
  594. X      (let* ((new (list 0 0))
  595. X         (lin new)
  596. X         (pp (cdr (nth (1- n) math-sum-int-pow-cache)))
  597. X         (p 2)
  598. X         (sum 0)
  599. X         q)
  600. X    (while pp
  601. X      (setq q (math-div (car pp) p)
  602. X        new (cons (math-mul q n) new)
  603. X        sum (math-add sum q)
  604. X        p (1+ p)
  605. X        pp (cdr pp)))
  606. X    (setcar lin (math-sub 1 (math-mul n sum)))
  607. X    (setq math-sum-int-pow-cache
  608. X          (nconc math-sum-int-pow-cache (list (nreverse new)))
  609. X          n (1+ n))))
  610. X    (nth pow math-sum-int-pow-cache))
  611. )
  612. (setq math-sum-int-pow-cache (list '(0 1)))
  613. X
  614. (defun math-to-exponentials (expr)
  615. X  (and (consp expr)
  616. X       (= (length expr) 2)
  617. X       (let ((x (nth 1 expr))
  618. X         (pi (if calc-symbolic-mode '(var pi var-pi) (math-pi)))
  619. X         (i (if calc-symbolic-mode '(var i var-i) '(cplx 0 1))))
  620. X     (cond ((eq (car expr) 'calcFunc-exp)
  621. X        (list '^ '(var e var-e) x))
  622. X           ((eq (car expr) 'calcFunc-sin)
  623. X        (or (eq calc-angle-mode 'rad)
  624. X            (setq x (list '/ (list '* x pi) 180)))
  625. X        (list '/ (list '-
  626. X                   (list '^ '(var e var-e) (list '* x i))
  627. X                   (list '^ '(var e var-e)
  628. X                     (list 'neg (list '* x i))))
  629. X              (list '* 2 i)))
  630. X           ((eq (car expr) 'calcFunc-cos)
  631. X        (or (eq calc-angle-mode 'rad)
  632. X            (setq x (list '/ (list '* x pi) 180)))
  633. X        (list '/ (list '+
  634. X                   (list '^ '(var e var-e)
  635. X                     (list '* x i))
  636. X                   (list '^ '(var e var-e)
  637. X                     (list 'neg (list '* x i))))
  638. X              2))
  639. X           ((eq (car expr) 'calcFunc-sinh)
  640. X        (list '/ (list '-
  641. X                   (list '^ '(var e var-e) x)
  642. X                   (list '^ '(var e var-e) (list 'neg x)))
  643. X              2))
  644. X           ((eq (car expr) 'calcFunc-cosh)
  645. X        (list '/ (list '+
  646. X                   (list '^ '(var e var-e) x)
  647. X                   (list '^ '(var e var-e) (list 'neg x)))
  648. X              2))
  649. X           (t nil))))
  650. )
  651. X
  652. (defun math-to-exps (expr)
  653. X  (cond (calc-symbolic-mode expr)
  654. X    ((Math-primp expr)
  655. X     (if (equal expr '(var e var-e)) (math-e) expr))
  656. X    ((and (eq (car expr) '^)
  657. X          (equal (nth 1 expr) '(var e var-e)))
  658. X     (list 'calcFunc-exp (nth 2 expr)))
  659. X    (t
  660. X     (cons (car expr) (mapcar 'math-to-exps (cdr expr)))))
  661. )
  662. X
  663. X
  664. (defun calcFunc-prod (expr var &optional low high step)
  665. X  (if math-disable-prods (math-reject-arg))
  666. X  (let* ((res (let* ((calc-internal-prec (+ calc-internal-prec 2)))
  667. X        (math-prod-rec expr var low high step)))
  668. X     (math-disable-prods t))
  669. X    (math-normalize res))
  670. )
  671. (setq math-disable-prods nil)
  672. X
  673. (defun math-prod-rec (expr var &optional low high step)
  674. X  (or low (setq low '(neg (var inf var-inf)) high '(var inf var-inf)))
  675. X  (and low (not high) (setq high '(var inf var-inf)))
  676. X  (let (t1 t2 t3 val)
  677. X    (setq val
  678. X      (cond
  679. X       ((not (math-expr-contains expr var))
  680. X        (math-pow expr (math-add (math-div (math-sub high low) (or step 1))
  681. X                     1)))
  682. X       ((and step (not (math-equal-int step 1)))
  683. X        (if (math-negp step)
  684. X        (math-prod-rec expr var high low (math-neg step))
  685. X          (let ((lo (math-simplify (math-div low step))))
  686. X        (if (math-known-num-integerp lo)
  687. X            (math-prod-rec (math-normalize
  688. X                    (math-expr-subst expr var
  689. X                             (math-mul step var)))
  690. X                   var lo (math-simplify (math-div high step)))
  691. X          (math-prod-rec (math-normalize
  692. X                  (math-expr-subst expr var
  693. X                           (math-add (math-mul step
  694. X                                       var)
  695. X                                 low)))
  696. X                 var 0
  697. X                 (math-simplify (math-div (math-sub high low)
  698. X                              step)))))))
  699. X       ((and (memq (car expr) '(* /))
  700. X         (setq t1 (math-prod-rec (nth 1 expr) var low high)
  701. X               t2 (math-prod-rec (nth 2 expr) var low high))
  702. X         (not (and (math-expr-calls t1 '(calcFunc-prod))
  703. X               (math-expr-calls t2 '(calcFunc-prod)))))
  704. X        (list (car expr) t1 t2))
  705. X       ((and (eq (car expr) '^)
  706. X         (not (math-expr-contains (nth 2 expr) var)))
  707. X        (math-pow (math-prod-rec (nth 1 expr) var low high)
  708. X              (nth 2 expr)))
  709. X       ((and (eq (car expr) '^)
  710. X         (not (math-expr-contains (nth 1 expr) var)))
  711. X        (math-pow (nth 1 expr)
  712. X              (calcFunc-sum (nth 2 expr) var low high)))
  713. X       ((eq (car expr) 'sqrt)
  714. X        (math-normalize (list 'calcFunc-sqrt
  715. X                  (list 'calcFunc-prod (nth 1 expr)
  716. X                    var low high))))
  717. X       ((eq (car expr) 'neg)
  718. X        (math-mul (math-pow -1 (math-add (math-sub high low) 1))
  719. X              (math-prod-rec (nth 1 expr) var low high)))
  720. X       ((eq (car expr) 'calcFunc-exp)
  721. X        (list 'calcFunc-exp (calcFunc-sum (nth 1 expr) var low high)))
  722. X       ((and (setq t1 (math-is-polynomial expr var 1))
  723. X         (setq t2
  724. X               (cond
  725. X            ((or (and (math-equal-int (nth 1 t1) 1)
  726. X                  (setq low (math-simplify
  727. X                         (math-add low (car t1)))
  728. X                    high (math-simplify
  729. X                          (math-add high (car t1)))))
  730. X                 (and (math-equal-int (nth 1 t1) -1)
  731. X                  (setq t2 low
  732. X                    low (math-simplify
  733. X                         (math-sub (car t1) high))
  734. X                    high (math-simplify
  735. X                          (math-sub (car t1) t2)))))
  736. X             (if (or (math-zerop low) (math-zerop high))
  737. X                 0
  738. X               (if (and (or (math-negp low) (math-negp high))
  739. X                    (or (math-num-integerp low)
  740. X                    (math-num-integerp high)))
  741. X                   (if (math-posp high)
  742. X                   0
  743. X                 (math-mul (math-pow -1
  744. X                             (math-add
  745. X                              (math-add low high) 1))
  746. X                       (list '/
  747. X                         (list 'calcFunc-fact
  748. X                               (math-neg low))
  749. X                         (list 'calcFunc-fact
  750. X                               (math-sub -1 high)))))
  751. X                 (list '/
  752. X                   (list 'calcFunc-fact high)
  753. X                   (list 'calcFunc-fact (math-sub low 1))))))
  754. X            ((and (or (and (math-equal-int (nth 1 t1) 2)
  755. X                       (setq t2 (math-simplify
  756. X                         (math-add (math-mul low 2)
  757. X                               (car t1)))
  758. X                         t3 (math-simplify
  759. X                         (math-add (math-mul high 2)
  760. X                               (car t1)))))
  761. X                  (and (math-equal-int (nth 1 t1) -2)
  762. X                       (setq t2 (math-simplify
  763. X                         (math-sub (car t1)
  764. X                               (math-mul high 2)))
  765. X                         t3 (math-simplify 
  766. X                         (math-sub (car t1)
  767. X                               (math-mul low
  768. X                                     2))))))
  769. X                  (or (math-integerp t2)
  770. X                  (and (math-messy-integerp t2)
  771. X                       (setq t2 (math-trunc t2)))
  772. X                  (math-integerp t3)
  773. X                  (and (math-messy-integerp t3)
  774. X                       (setq t3 (math-trunc t3)))))
  775. X             (if (or (math-zerop t2) (math-zerop t3))
  776. X                 0
  777. X               (if (or (math-evenp t2) (math-evenp t3))
  778. X                   (if (or (math-negp t2) (math-negp t3))
  779. X                   (if (math-posp high)
  780. X                       0
  781. X                     (list '/
  782. X                       (list 'calcFunc-dfact
  783. X                         (math-neg t2))
  784. X                       (list 'calcFunc-dfact
  785. X                         (math-sub -2 t3))))
  786. X                 (list '/
  787. X                       (list 'calcFunc-dfact t3)
  788. X                       (list 'calcFunc-dfact
  789. X                         (math-sub t2 2))))
  790. X                 (if (math-negp t3)
  791. X                 (list '*
  792. X                       (list '^ -1
  793. X                         (list '/ (list '- (list '- t2 t3)
  794. X                                2)
  795. X                           2))
  796. X                       (list '/
  797. X                         (list 'calcFunc-dfact
  798. X                           (math-neg t2))
  799. X                         (list 'calcFunc-dfact
  800. X                           (math-sub -2 t3))))
  801. X                   (if (math-posp t2)
  802. X                   (list '/
  803. X                     (list 'calcFunc-dfact t3)
  804. X                     (list 'calcFunc-dfact
  805. X                           (math-sub t2 2)))
  806. X                 nil))))))))
  807. X        t2)))
  808. X    (if (equal val '(var nan var-nan)) (setq val nil))
  809. X    (or val
  810. X    (let* ((math-tabulate-initial 1)
  811. X           (math-tabulate-function 'calcFunc-prod))
  812. X      (calcFunc-table expr var low high))))
  813. )
  814. X
  815. X
  816. X
  817. X
  818. ;;; Attempt to reduce lhs = rhs to solve-var = rhs', where solve-var appears
  819. ;;; in lhs but not in rhs or rhs'; return rhs'.
  820. ;;; Uses global values: solve-*.
  821. (defun math-try-solve-for (lhs rhs &optional sign no-poly)
  822. X  (let (t1 t2 t3)
  823. X    (cond ((equal lhs solve-var)
  824. X       (setq math-solve-sign sign)
  825. X       (if (eq solve-full 'all)
  826. X           (let ((vec (list 'vec (math-evaluate-expr rhs)))
  827. X             newvec var p)
  828. X         (while math-solve-ranges
  829. X           (setq p (car math-solve-ranges)
  830. X             var (car p)
  831. X             newvec (list 'vec))
  832. X           (while (setq p (cdr p))
  833. X             (setq newvec (nconc newvec
  834. X                     (cdr (math-expr-subst
  835. X                           vec var (car p))))))
  836. X           (setq vec newvec
  837. X             math-solve-ranges (cdr math-solve-ranges)))
  838. X         (math-normalize vec))
  839. X         rhs))
  840. X      ((Math-primp lhs)
  841. X       nil)
  842. X      ((and (eq (car lhs) '-)
  843. X        (eq (car-safe (nth 1 lhs)) (car-safe (nth 2 lhs)))
  844. X        (Math-zerop rhs)
  845. X        (= (length (nth 1 lhs)) 2)
  846. X        (= (length (nth 2 lhs)) 2)
  847. X        (setq t1 (get (car (nth 1 lhs)) 'math-inverse))
  848. X        (setq t2 (funcall t1 '(var SOLVEDUM SOLVEDUM)))
  849. X        (eq (math-expr-contains-count t2 '(var SOLVEDUM SOLVEDUM)) 1)
  850. X        (setq t3 (math-solve-above-dummy t2))
  851. X        (setq t1 (math-try-solve-for (math-sub (nth 1 (nth 1 lhs))
  852. X                               (math-expr-subst
  853. X                            t2 t3
  854. X                            (nth 1 (nth 2 lhs))))
  855. X                         0)))
  856. X       t1)
  857. X      ((eq (car lhs) 'neg)
  858. X       (math-try-solve-for (nth 1 lhs) (math-neg rhs)
  859. X                   (and sign (- sign))))
  860. X      ((and (not (eq solve-full 't)) (math-try-solve-prod)))
  861. X      ((and (not no-poly)
  862. X        (setq t2 (math-decompose-poly lhs solve-var 15 rhs)))
  863. X       (setq t1 (cdr (nth 1 t2))
  864. X         t1 (let ((math-solve-ranges math-solve-ranges))
  865. X              (cond ((= (length t1) 5)
  866. X                 (apply 'math-solve-quartic (car t2) t1))
  867. X                ((= (length t1) 4)
  868. X                 (apply 'math-solve-cubic (car t2) t1))
  869. X                ((= (length t1) 3)
  870. X                 (apply 'math-solve-quadratic (car t2) t1))
  871. X                ((= (length t1) 2)
  872. X                 (apply 'math-solve-linear (car t2) sign t1))
  873. X                (solve-full
  874. X                 (math-poly-all-roots (car t2) t1))
  875. X                (calc-symbolic-mode nil)
  876. X                (t
  877. X                 (math-try-solve-for
  878. X                  (car t2)
  879. X                  (math-poly-any-root (reverse t1) 0 t)
  880. X                  nil t)))))
  881. X       (if t1
  882. X           (if (eq (nth 2 t2) 1)
  883. X           t1
  884. X         (math-solve-prod t1 (math-try-solve-for (nth 2 t2) 0 nil t)))
  885. X         (calc-record-why "*Unable to find a symbolic solution")
  886. X         nil))
  887. X      ((and (math-solve-find-root-term lhs nil)
  888. X        (eq (math-expr-contains-count lhs t1) 1))   ; just in case
  889. X       (math-try-solve-for (math-simplify
  890. X                (math-sub (if (or t3 (math-evenp t2))
  891. X                          (math-pow t1 t2)
  892. X                        (math-neg (math-pow t1 t2)))
  893. X                      (math-expand-power
  894. X                       (math-sub (math-normalize
  895. X                              (math-expr-subst
  896. X                               lhs t1 0))
  897. X                             rhs)
  898. X                       t2 solve-var)))
  899. X                   0))
  900. X      ((eq (car lhs) '+)
  901. X       (cond ((not (math-expr-contains (nth 1 lhs) solve-var))
  902. X          (math-try-solve-for (nth 2 lhs)
  903. X                      (math-sub rhs (nth 1 lhs))
  904. X                      sign))
  905. X         ((not (math-expr-contains (nth 2 lhs) solve-var))
  906. X          (math-try-solve-for (nth 1 lhs)
  907. X                      (math-sub rhs (nth 2 lhs))
  908. X                      sign))))
  909. X      ((eq (car lhs) 'calcFunc-eq)
  910. X       (math-try-solve-for (math-sub (nth 1 lhs) (nth 2 lhs))
  911. X                   rhs sign no-poly))
  912. X      ((eq (car lhs) '-)
  913. X       (cond ((or (and (eq (car-safe (nth 1 lhs)) 'calcFunc-sin)
  914. X               (eq (car-safe (nth 2 lhs)) 'calcFunc-cos))
  915. X              (and (eq (car-safe (nth 1 lhs)) 'calcFunc-cos)
  916. X               (eq (car-safe (nth 2 lhs)) 'calcFunc-sin)))
  917. X          (math-try-solve-for (math-sub (nth 1 lhs)
  918. X                        (list (car (nth 1 lhs))
  919. X                              (math-sub
  920. X                               (math-quarter-circle t)
  921. X                               (nth 1 (nth 2 lhs)))))
  922. X                      rhs))
  923. X         ((not (math-expr-contains (nth 1 lhs) solve-var))
  924. X          (math-try-solve-for (nth 2 lhs)
  925. X                      (math-sub (nth 1 lhs) rhs)
  926. X                      (and sign (- sign))))
  927. X         ((not (math-expr-contains (nth 2 lhs) solve-var))
  928. X          (math-try-solve-for (nth 1 lhs)
  929. X                      (math-add rhs (nth 2 lhs))
  930. X                      sign))))
  931. X      ((and (eq solve-full 't) (math-try-solve-prod)))
  932. X      ((and (eq (car lhs) '%)
  933. X        (not (math-expr-contains (nth 2 lhs) solve-var)))
  934. X       (math-try-solve-for (nth 1 lhs) (math-add rhs
  935. X                             (math-solve-get-int
  936. X                              (nth 2 lhs)))))
  937. X      ((eq (car lhs) 'calcFunc-log)
  938. X       (cond ((not (math-expr-contains (nth 2 lhs) solve-var))
  939. X          (math-try-solve-for (nth 1 lhs) (math-pow (nth 2 lhs) rhs)))
  940. X         ((not (math-expr-contains (nth 1 lhs) solve-var))
  941. X          (math-try-solve-for (nth 2 lhs) (math-pow
  942. X                           (nth 1 lhs)
  943. X                           (math-div 1 rhs))))))
  944. X      ((and (= (length lhs) 2)
  945. X        (symbolp (car lhs))
  946. X        (setq t1 (get (car lhs) 'math-inverse))
  947. X        (setq t2 (funcall t1 rhs)))
  948. X       (setq t1 (get (car lhs) 'math-inverse-sign))
  949. X       (math-try-solve-for (nth 1 lhs) (math-normalize t2)
  950. X                   (and sign t1
  951. X                    (if (integerp t1)
  952. X                    (* t1 sign)
  953. X                      (funcall t1 lhs sign)))))
  954. X      ((and (symbolp (car lhs))
  955. X        (setq t1 (get (car lhs) 'math-inverse-n))
  956. X        (setq t2 (funcall t1 lhs rhs)))
  957. X       t2)
  958. X      ((setq t1 (math-expand-formula lhs))
  959. X       (math-try-solve-for t1 rhs sign))
  960. X      (t
  961. X       (calc-record-why "*No inverse known" lhs)
  962. X       nil)))
  963. )
  964. X
  965. (setq math-solve-ranges nil)
  966. X
  967. (defun math-try-solve-prod ()
  968. X  (cond ((eq (car lhs) '*)
  969. X     (cond ((not (math-expr-contains (nth 1 lhs) solve-var))
  970. X        (math-try-solve-for (nth 2 lhs)
  971. X                    (math-div rhs (nth 1 lhs))
  972. X                    (math-solve-sign sign (nth 1 lhs))))
  973. X           ((not (math-expr-contains (nth 2 lhs) solve-var))
  974. X        (math-try-solve-for (nth 1 lhs)
  975. X                    (math-div rhs (nth 2 lhs))
  976. X                    (math-solve-sign sign (nth 2 lhs))))
  977. X           ((Math-zerop rhs)
  978. X        (math-solve-prod (let ((math-solve-ranges math-solve-ranges))
  979. X                   (math-try-solve-for (nth 2 lhs) 0))
  980. X                 (math-try-solve-for (nth 1 lhs) 0)))))
  981. X    ((eq (car lhs) '/)
  982. X     (cond ((not (math-expr-contains (nth 1 lhs) solve-var))
  983. X        (math-try-solve-for (nth 2 lhs)
  984. X                    (math-div (nth 1 lhs) rhs)
  985. X                    (math-solve-sign sign (nth 1 lhs))))
  986. X           ((not (math-expr-contains (nth 2 lhs) solve-var))
  987. X        (math-try-solve-for (nth 1 lhs)
  988. X                    (math-mul rhs (nth 2 lhs))
  989. X                    (math-solve-sign sign (nth 2 lhs))))
  990. X           ((setq t1 (math-try-solve-for (math-sub (nth 1 lhs)
  991. X                               (math-mul (nth 2 lhs)
  992. X                                 rhs))
  993. X                         0))
  994. X        t1)))
  995. X    ((eq (car lhs) '^)
  996. X     (cond ((not (math-expr-contains (nth 1 lhs) solve-var))
  997. X        (math-try-solve-for
  998. X         (nth 2 lhs)
  999. X         (math-add (math-normalize
  1000. X                (list 'calcFunc-log rhs (nth 1 lhs)))
  1001. X               (math-div
  1002. X                (math-mul 2
  1003. X                      (math-mul '(var pi var-pi)
  1004. X                        (math-solve-get-int
  1005. X                         '(var i var-i))))
  1006. X                (math-normalize
  1007. X                 (list 'calcFunc-ln (nth 1 lhs)))))))
  1008. X           ((not (math-expr-contains (nth 2 lhs) solve-var))
  1009. X        (cond ((and (integerp (nth 2 lhs))
  1010. X                (>= (nth 2 lhs) 2)
  1011. X                (setq t1 (math-integer-log2 (nth 2 lhs))))
  1012. X               (setq t2 rhs)
  1013. X               (if (and (eq solve-full t)
  1014. X                (math-known-realp (nth 1 lhs)))
  1015. X               (progn
  1016. X                 (while (>= (setq t1 (1- t1)) 0)
  1017. X                   (setq t2 (list 'calcFunc-sqrt t2)))
  1018. X                 (setq t2 (math-solve-get-sign t2)))
  1019. X             (while (>= (setq t1 (1- t1)) 0)
  1020. X               (setq t2 (math-solve-get-sign
  1021. X                     (math-normalize
  1022. X                      (list 'calcFunc-sqrt t2))))))
  1023. X               (math-try-solve-for
  1024. X            (nth 1 lhs)
  1025. X            (math-normalize t2)))
  1026. X              ((math-looks-negp (nth 2 lhs))
  1027. X               (math-try-solve-for
  1028. X            (list '^ (nth 1 lhs) (math-neg (nth 2 lhs)))
  1029. X            (math-div 1 rhs)))
  1030. X              ((and (eq solve-full t)
  1031. X                (Math-integerp (nth 2 lhs))
  1032. X                (math-known-realp (nth 1 lhs)))
  1033. X               (setq t1 (math-normalize
  1034. X                 (list 'calcFunc-nroot rhs (nth 2 lhs))))
  1035. X               (if (math-evenp (nth 2 lhs))
  1036. X               (setq t1 (math-solve-get-sign t1)))
  1037. X               (math-try-solve-for
  1038. X            (nth 1 lhs) t1
  1039. X            (and sign
  1040. X                 (math-oddp (nth 2 lhs))
  1041. X                 (math-solve-sign sign (nth 2 lhs)))))
  1042. X              (t (math-try-solve-for
  1043. X              (nth 1 lhs)
  1044. X              (math-mul
  1045. X               (math-normalize
  1046. X                (list 'calcFunc-exp
  1047. X                  (if (Math-realp (nth 2 lhs))
  1048. X                      (math-div (math-mul
  1049. X                         '(var pi var-pi)
  1050. X                         (math-solve-get-int
  1051. X                          '(var i var-i)
  1052. X                          (and (integerp (nth 2 lhs))
  1053. X                               (math-abs
  1054. X                            (nth 2 lhs)))))
  1055. X                        (math-div (nth 2 lhs) 2))
  1056. X                    (math-div (math-mul
  1057. X                           2
  1058. X                           (math-mul
  1059. X                        '(var pi var-pi)
  1060. X                        (math-solve-get-int
  1061. X                         '(var i var-i)
  1062. X                         (and (integerp (nth 2 lhs))
  1063. X                              (math-abs
  1064. X                               (nth 2 lhs))))))
  1065. X                          (nth 2 lhs)))))
  1066. X               (math-normalize
  1067. X                (list 'calcFunc-nroot
  1068. X                  rhs
  1069. X                  (nth 2 lhs))))
  1070. X              (and sign
  1071. X                   (math-oddp (nth 2 lhs))
  1072. X                   (math-solve-sign sign (nth 2 lhs)))))))))
  1073. X    (t nil))
  1074. )
  1075. X
  1076. (defun math-solve-prod (lsoln rsoln)
  1077. X  (cond ((null lsoln)
  1078. X     rsoln)
  1079. X    ((null rsoln)
  1080. X     lsoln)
  1081. X    ((eq solve-full 'all)
  1082. X     (cons 'vec (append (cdr lsoln) (cdr rsoln))))
  1083. X    (solve-full
  1084. X     (list 'calcFunc-if
  1085. X           (list 'calcFunc-gt (math-solve-get-sign 1) 0)
  1086. X           lsoln
  1087. X           rsoln))
  1088. X    (t lsoln))
  1089. )
  1090. X
  1091. ;;; This deals with negative, fractional, and symbolic powers of "x".
  1092. (defun math-solve-poly-funny-powers (sub-rhs)    ; uses "t1", "t2"
  1093. X  (setq t1 lhs)
  1094. X  (let ((pp math-poly-neg-powers)
  1095. X    fac)
  1096. X    (while pp
  1097. X      (setq fac (math-pow (car pp) (or math-poly-mult-powers 1))
  1098. X        t1 (math-mul t1 fac)
  1099. X        rhs (math-mul rhs fac)
  1100. X        pp (cdr pp))))
  1101. X  (if sub-rhs (setq t1 (math-sub t1 rhs)))
  1102. X  (let ((math-poly-neg-powers nil))
  1103. X    (setq t2 (math-mul (or math-poly-mult-powers 1)
  1104. X               (let ((calc-prefer-frac t))
  1105. X             (math-div 1 math-poly-frac-powers)))
  1106. X      t1 (math-is-polynomial (math-simplify (calcFunc-expand t1)) b 50)))
  1107. )
  1108. X
  1109. ;;; This converts "a x^8 + b x^5 + c x^2" to "(a (x^3)^2 + b (x^3) + c) * x^2".
  1110. (defun math-solve-crunch-poly (max-degree)   ; uses "t1", "t3"
  1111. X  (let ((count 0))
  1112. X    (while (and t1 (Math-zerop (car t1)))
  1113. X      (setq t1 (cdr t1)
  1114. X        count (1+ count)))
  1115. X    (and t1
  1116. X     (let* ((degree (1- (length t1)))
  1117. X        (scale degree))
  1118. X       (while (and (> scale 1) (= (car t3) 1))
  1119. X         (and (= (% degree scale) 0)
  1120. X          (let ((p t1)
  1121. X            (n 0)
  1122. X            (new-t1 nil)
  1123. X            (okay t))
  1124. X            (while (and p okay)
  1125. X              (if (= (% n scale) 0)
  1126. X              (setq new-t1 (nconc new-t1 (list (car p))))
  1127. X            (or (Math-zerop (car p))
  1128. X                (setq okay nil)))
  1129. X              (setq p (cdr p)
  1130. X                n (1+ n)))
  1131. X            (if okay
  1132. X            (setq t3 (cons scale (cdr t3))
  1133. X                  t1 new-t1))))
  1134. X         (setq scale (1- scale)))
  1135. X       (setq t3 (list (math-mul (car t3) t2) (math-mul count t2)))
  1136. X       (<= (1- (length t1)) max-degree))))
  1137. )
  1138. X
  1139. (defun calcFunc-poly (expr var &optional degree)
  1140. X  (if degree
  1141. X      (or (natnump degree) (math-reject-arg degree 'fixnatnump))
  1142. X    (setq degree 50))
  1143. X  (let ((p (math-is-polynomial expr var degree 'gen)))
  1144. X    (if p
  1145. X    (if (equal p '(0))
  1146. X        (list 'vec)
  1147. X      (cons 'vec p))
  1148. X      (math-reject-arg expr "Expected a polynomial")))
  1149. )
  1150. X
  1151. (defun calcFunc-gpoly (expr var &optional degree)
  1152. X  (if degree
  1153. X      (or (natnump degree) (math-reject-arg degree 'fixnatnump))
  1154. X    (setq degree 50))
  1155. X  (let* ((math-poly-base-variable var)
  1156. X     (d (math-decompose-poly expr var degree nil)))
  1157. X    (if d
  1158. X    (cons 'vec d)
  1159. X      (math-reject-arg expr "Expected a polynomial")))
  1160. )
  1161. X
  1162. (defun math-decompose-poly (lhs solve-var degree sub-rhs)
  1163. X  (let ((rhs (or sub-rhs 1))
  1164. X    t1 t2 t3)
  1165. X    (setq t2 (math-polynomial-base
  1166. X          lhs
  1167. X          (function
  1168. X           (lambda (b)
  1169. X         (let ((math-poly-neg-powers '(1))
  1170. X               (math-poly-mult-powers nil)
  1171. X               (math-poly-frac-powers 1)
  1172. X               (math-poly-exp-base t))
  1173. X           (and (not (equal b lhs))
  1174. X            (or (not (memq (car-safe b) '(+ -))) sub-rhs)
  1175. X            (setq t3 '(1 0) t2 1
  1176. X                  t1 (math-is-polynomial lhs b 50))
  1177. X            (if (and (equal math-poly-neg-powers '(1))
  1178. X                 (memq math-poly-mult-powers '(nil 1))
  1179. X                 (eq math-poly-frac-powers 1)
  1180. X                 sub-rhs)
  1181. X                (setq t1 (cons (math-sub (car t1) rhs)
  1182. X                       (cdr t1)))
  1183. X              (math-solve-poly-funny-powers sub-rhs))
  1184. X            (math-solve-crunch-poly degree)
  1185. X            (or (math-expr-contains b solve-var)
  1186. X                (math-expr-contains (car t3) solve-var))))))))
  1187. X    (if t2
  1188. X    (list (math-pow t2 (car t3))
  1189. X          (cons 'vec t1)
  1190. X          (if sub-rhs
  1191. X          (math-pow t2 (nth 1 t3))
  1192. X        (math-div (math-pow t2 (nth 1 t3)) rhs)))))
  1193. )
  1194. X
  1195. (defun math-solve-linear (var sign b a)
  1196. X  (math-try-solve-for var
  1197. X              (math-div (math-neg b) a)
  1198. X              (math-solve-sign sign a)
  1199. X              t)
  1200. )
  1201. X
  1202. (defun math-solve-quadratic (var c b a)
  1203. X  (math-try-solve-for
  1204. X   var
  1205. X   (if (math-looks-evenp b)
  1206. X       (let ((halfb (math-div b 2)))
  1207. X     (math-div
  1208. X      (math-add
  1209. X       (math-neg halfb)
  1210. X       (math-solve-get-sign
  1211. X        (math-normalize
  1212. X         (list 'calcFunc-sqrt
  1213. X           (math-add (math-sqr halfb)
  1214. X                 (math-mul (math-neg c) a))))))
  1215. X      a))
  1216. X     (math-div
  1217. X      (math-add
  1218. X       (math-neg b)
  1219. X       (math-solve-get-sign
  1220. X    (math-normalize
  1221. X     (list 'calcFunc-sqrt
  1222. X           (math-add (math-sqr b)
  1223. X             (math-mul 4 (math-mul (math-neg c) a)))))))
  1224. X      (math-mul 2 a)))
  1225. X   nil t)
  1226. )
  1227. X
  1228. (defun math-solve-cubic (var d c b a)
  1229. X  (let* ((p (math-div b a))
  1230. X     (q (math-div c a))
  1231. X     (r (math-div d a))
  1232. X     (psqr (math-sqr p))
  1233. X     (aa (math-sub q (math-div psqr 3)))
  1234. X     (bb (math-add r
  1235. X               (math-div (math-sub (math-mul 2 (math-mul psqr p))
  1236. X                       (math-mul 9 (math-mul p q)))
  1237. X                 27)))
  1238. X     m)
  1239. X    (if (Math-zerop aa)
  1240. X    (math-try-solve-for (math-pow (math-add var (math-div p 3)) 3)
  1241. X                (math-neg bb) nil t)
  1242. X      (if (Math-zerop bb)
  1243. X      (math-try-solve-for
  1244. X       (math-mul (math-add var (math-div p 3))
  1245. X             (math-add (math-sqr (math-add var (math-div p 3)))
  1246. X                   aa))
  1247. X       0 nil t)
  1248. X    (setq m (math-mul 2 (list 'calcFunc-sqrt (math-div aa -3))))
  1249. X    (math-try-solve-for
  1250. X     var
  1251. X     (math-sub
  1252. X      (math-normalize
  1253. X       (math-mul
  1254. X        m
  1255. X        (list 'calcFunc-cos
  1256. X          (math-div
  1257. X           (math-sub (list 'calcFunc-arccos
  1258. X                   (math-div (math-mul 3 bb)
  1259. X                         (math-mul aa m)))
  1260. X                 (math-mul 2
  1261. X                       (math-mul
  1262. X                    (math-add 1 (math-solve-get-int
  1263. X                             1 3))
  1264. X                    (math-half-circle
  1265. X                     calc-symbolic-mode))))
  1266. X           3))))
  1267. X      (math-div p 3))
  1268. X     nil t))))
  1269. )
  1270. X
  1271. (defun math-solve-quartic (var d c b a aa)
  1272. X  (setq a (math-div a aa))
  1273. X  (setq b (math-div b aa))
  1274. X  (setq c (math-div c aa))
  1275. X  (setq d (math-div d aa))
  1276. X  (math-try-solve-for
  1277. X   var
  1278. X   (let* ((asqr (math-sqr a))
  1279. X      (asqr4 (math-div asqr 4))
  1280. X      (y (let ((solve-full nil)
  1281. X           calc-next-why)
  1282. X           (math-solve-cubic solve-var
  1283. X                 (math-sub (math-sub
  1284. X                        (math-mul 4 (math-mul b d))
  1285. X                        (math-mul asqr d))
  1286. X                       (math-sqr c))
  1287. X                 (math-sub (math-mul a c)
  1288. X                       (math-mul 4 d))
  1289. X                 (math-neg b)
  1290. X                 1)))
  1291. X      (rsqr (math-add (math-sub asqr4 b) y))
  1292. X      (r (list 'calcFunc-sqrt rsqr))
  1293. X      (sign1 (math-solve-get-sign 1))
  1294. X      (de (list 'calcFunc-sqrt
  1295. X            (math-add
  1296. X             (math-sub (math-mul 3 asqr4)
  1297. X                   (math-mul 2 b))
  1298. X             (if (Math-zerop rsqr)
  1299. X             (math-mul
  1300. X              2
  1301. X              (math-mul sign1
  1302. X                    (list 'calcFunc-sqrt
  1303. X                      (math-sub (math-sqr y)
  1304. X                            (math-mul 4 d)))))
  1305. X               (math-sub
  1306. X            (math-mul sign1
  1307. X                  (math-div
  1308. X                   (math-sub (math-sub
  1309. X                          (math-mul 4 (math-mul a b))
  1310. X                          (math-mul 8 c))
  1311. X                         (math-mul asqr a))
  1312. X                   (math-mul 4 r)))
  1313. X            rsqr))))))
  1314. X     (math-normalize
  1315. X      (math-sub (math-add (math-mul sign1 (math-div r 2))
  1316. X              (math-solve-get-sign (math-div de 2)))
  1317. X        (math-div a 4))))
  1318. X   nil t)
  1319. )
  1320. X
  1321. (defun math-poly-all-roots (var p &optional math-factoring)
  1322. X  (catch 'ouch
  1323. X    (let* ((math-symbolic-solve calc-symbolic-mode)
  1324. X       (roots nil)
  1325. X       (deg (1- (length p)))
  1326. X       (orig-p (reverse p))
  1327. X       (math-int-coefs nil)
  1328. X       (math-int-scale nil)
  1329. X       (math-double-roots nil)
  1330. X       (math-int-factors nil)
  1331. X       (math-int-threshold nil)
  1332. X       (pp p))
  1333. X      ;; If rational coefficients, look for exact rational factors.
  1334. X      (while (and pp (Math-ratp (car pp)))
  1335. X    (setq pp (cdr pp)))
  1336. X      (if pp
  1337. X      (if (or math-factoring math-symbolic-solve)
  1338. X          (throw 'ouch nil))
  1339. X    (let ((lead (car orig-p))
  1340. X          (calc-prefer-frac t)
  1341. X          (scale (apply 'math-lcm-denoms p)))
  1342. X      (setq math-int-scale (math-abs (math-mul scale lead))
  1343. X        math-int-threshold (math-div '(float 5 -2) math-int-scale)
  1344. X        math-int-coefs (cdr (math-div (cons 'vec orig-p) lead)))))
  1345. X      (if (> deg 4)
  1346. X      (let ((calc-prefer-frac nil)
  1347. X        (calc-symbolic-mode nil)
  1348. X        (pp p)
  1349. X        (def-p (copy-sequence orig-p)))
  1350. X        (while pp
  1351. X          (if (Math-numberp (car pp))
  1352. X          (setq pp (cdr pp))
  1353. X        (throw 'ouch nil)))
  1354. X        (while (> deg (if math-symbolic-solve 2 4))
  1355. X          (let* ((x (math-poly-any-root def-p '(float 0 0) nil))
  1356. X             b c pp)
  1357. X        (if (and (eq (car-safe x) 'cplx)
  1358. X             (math-nearly-zerop (nth 2 x) (nth 1 x)))
  1359. X            (setq x (calcFunc-re x)))
  1360. X        (or math-factoring
  1361. X            (setq roots (cons x roots)))
  1362. X        (or (math-numberp x)
  1363. X            (setq x (math-evaluate-expr x)))
  1364. X        (setq pp def-p
  1365. X              b (car def-p))
  1366. X        (while (setq pp (cdr pp))
  1367. X          (setq c (car pp))
  1368. X          (setcar pp b)
  1369. X          (setq b (math-add (math-mul x b) c)))
  1370. X        (setq def-p (cdr def-p)
  1371. X              deg (1- deg))))
  1372. X        (setq p (reverse def-p))))
  1373. X      (if (> deg 1)
  1374. X      (let ((solve-var '(var DUMMY var-DUMMY))
  1375. X        (math-solve-sign nil)
  1376. X        (math-solve-ranges nil)
  1377. X        (solve-full 'all))
  1378. X        (if (= (length p) (length math-int-coefs))
  1379. X        (setq p (reverse math-int-coefs)))
  1380. X        (setq roots (append (cdr (apply (cond ((= deg 2)
  1381. X                           'math-solve-quadratic)
  1382. X                          ((= deg 3)
  1383. X                           'math-solve-cubic)
  1384. X                          (t
  1385. X                           'math-solve-quartic))
  1386. X                        solve-var p))
  1387. X                roots)))
  1388. X    (if (> deg 0)
  1389. X        (setq roots (cons (math-div (math-neg (car p)) (nth 1 p))
  1390. X                  roots))))
  1391. X      (if math-factoring
  1392. X      (progn
  1393. X        (while roots
  1394. X          (math-poly-integer-root (car roots))
  1395. X          (setq roots (cdr roots)))
  1396. X        (list math-int-factors (nreverse math-int-coefs) math-int-scale))
  1397. X    (let ((vec nil) res)
  1398. X      (while roots
  1399. X        (let ((root (car roots))
  1400. X          (solve-full (and solve-full 'all)))
  1401. X          (if (math-floatp root)
  1402. X          (setq root (math-poly-any-root orig-p root t)))
  1403. X          (setq vec (append vec
  1404. X                (cdr (or (math-try-solve-for var root nil t)
  1405. X                     (throw 'ouch nil))))))
  1406. X        (setq roots (cdr roots)))
  1407. X      (setq vec (cons 'vec (nreverse vec)))
  1408. X      (if math-symbolic-solve
  1409. X          (setq vec (math-normalize vec)))
  1410. X      (if (eq solve-full t)
  1411. X          (list 'calcFunc-subscr
  1412. X            vec
  1413. X            (math-solve-get-int 1 (1- (length orig-p)) 1))
  1414. X        vec)))))
  1415. )
  1416. (setq math-symbolic-solve nil)
  1417. X
  1418. (defun math-lcm-denoms (&rest fracs)
  1419. X  (let ((den 1))
  1420. X    (while fracs
  1421. X      (if (eq (car-safe (car fracs)) 'frac)
  1422. X      (setq den (calcFunc-lcm den (nth 2 (car fracs)))))
  1423. X      (setq fracs (cdr fracs)))
  1424. X    den)
  1425. )
  1426. X
  1427. (defun math-poly-any-root (p x polish)    ; p is a reverse poly coeff list
  1428. X  (let* ((newt (if (math-zerop x)
  1429. X           (math-poly-newton-root
  1430. X            p '(cplx (float 123 -6) (float 1 -4)) 4)
  1431. X         (math-poly-newton-root p x 4)))
  1432. X     (res (if (math-zerop (cdr newt))
  1433. X          (car newt)
  1434. X        (if (and (math-lessp (cdr newt) '(float 1 -3)) (not polish))
  1435. X            (setq newt (math-poly-newton-root p (car newt) 30)))
  1436. X        (if (math-zerop (cdr newt))
  1437. X            (car newt)
  1438. X          (math-poly-laguerre-root p x polish)))))
  1439. X    (and math-symbolic-solve (math-floatp res)
  1440. X     (throw 'ouch nil))
  1441. X    res)
  1442. )
  1443. X
  1444. (defun math-poly-newton-root (p x iters)
  1445. X  (let* ((calc-prefer-frac nil)
  1446. X     (calc-symbolic-mode nil)
  1447. X     (try-integer math-int-coefs)
  1448. X     (dx x) b d)
  1449. X    (while (and (> (setq iters (1- iters)) 0)
  1450. X        (let ((pp p))
  1451. X          (math-working "newton" x)
  1452. X          (setq b (car p)
  1453. X            d 0)
  1454. X          (while (setq pp (cdr pp))
  1455. X            (setq d (math-add (math-mul x d) b)
  1456. X              b (math-add (math-mul x b) (car pp))))
  1457. X          (not (math-zerop d)))
  1458. X        (progn
  1459. X          (setq dx (math-div b d)
  1460. X            x (math-sub x dx))
  1461. X          (if try-integer
  1462. X              (let ((adx (math-abs-approx dx)))
  1463. X            (and (math-lessp adx math-int-threshold)
  1464. X                 (let ((iroot (math-poly-integer-root x)))
  1465. X                   (if iroot
  1466. X                   (setq x iroot dx 0)
  1467. X                 (setq try-integer nil))))))
  1468. X          (or (not (or (eq dx 0)
  1469. X                   (math-nearly-zerop dx (math-abs-approx x))))
  1470. X              (progn (setq dx 0) nil)))))
  1471. X    (cons x (if (math-zerop x)
  1472. X        1 (math-div (math-abs-approx dx) (math-abs-approx x)))))
  1473. )
  1474. X
  1475. (defun math-poly-integer-root (x)
  1476. X  (and (math-lessp (calcFunc-xpon (math-abs-approx x)) calc-internal-prec)
  1477. X       math-int-coefs
  1478. X       (let* ((calc-prefer-frac t)
  1479. X          (xre (calcFunc-re x))
  1480. X          (xim (calcFunc-im x))
  1481. X          (xresq (math-sqr xre))
  1482. X          (ximsq (math-sqr xim)))
  1483. X     (if (math-lessp ximsq (calcFunc-scf xresq -1))
  1484. X         ;; Look for linear factor
  1485. X         (let* ((rnd (math-div (math-round (math-mul xre math-int-scale))
  1486. X                   math-int-scale))
  1487. X            (icp math-int-coefs)
  1488. X            (rem (car icp))
  1489. X            (newcoef nil))
  1490. X           (while (setq icp (cdr icp))
  1491. X         (setq newcoef (cons rem newcoef)
  1492. X               rem (math-add (car icp)
  1493. X                     (math-mul rem rnd))))
  1494. X           (and (math-zerop rem)
  1495. X            (progn
  1496. X              (setq math-int-coefs (nreverse newcoef)
  1497. X                math-int-factors (cons (list (math-neg rnd))
  1498. X                           math-int-factors))
  1499. X              rnd)))
  1500. X       ;; Look for irreducible quadratic factor
  1501. X       (let* ((rnd1 (math-div (math-round
  1502. X                   (math-mul xre (math-mul -2 math-int-scale)))
  1503. X                  math-int-scale))
  1504. X          (sqscale (math-sqr math-int-scale))
  1505. X          (rnd0 (math-div (math-round (math-mul (math-add xresq ximsq)
  1506. X                            sqscale))
  1507. X                  sqscale))
  1508. X          (rem1 (car math-int-coefs))
  1509. X          (icp (cdr math-int-coefs))
  1510. X          (rem0 (car icp))
  1511. X          (newcoef nil)
  1512. X          (found (assoc (list rnd0 rnd1 (math-posp xim))
  1513. X                math-double-roots))
  1514. X          this)
  1515. X         (if found
  1516. X         (setq math-double-roots (delq found math-double-roots)
  1517. X               rem0 0 rem1 0)
  1518. X           (while (setq icp (cdr icp))
  1519. X         (setq this rem1
  1520. X               newcoef (cons rem1 newcoef)
  1521. X               rem1 (math-sub rem0 (math-mul this rnd1))
  1522. X               rem0 (math-sub (car icp) (math-mul this rnd0)))))
  1523. X         (and (math-zerop rem0)
  1524. X          (math-zerop rem1)
  1525. X          (let ((aa (math-div rnd1 -2)))
  1526. X            (or found (setq math-int-coefs (reverse newcoef)
  1527. X                    math-double-roots (cons (list
  1528. X                                 (list
  1529. X                                  rnd0 rnd1
  1530. X                                  (math-negp xim)))
  1531. X                                math-double-roots)
  1532. X                    math-int-factors (cons (cons rnd0 rnd1)
  1533. X                               math-int-factors)))
  1534. X            (math-add aa
  1535. X                  (let ((calc-symbolic-mode math-symbolic-solve))
  1536. X                (math-mul (math-sqrt (math-sub (math-sqr aa)
  1537. X                                   rnd0))
  1538. X                      (if (math-negp xim) -1 1))))))))))
  1539. )
  1540. (setq math-int-coefs nil)
  1541. X
  1542. ;;; The following routine is from Numerical Recipes, section 9.5.
  1543. (defun math-poly-laguerre-root (p x polish)
  1544. X  (let* ((calc-prefer-frac nil)
  1545. X     (calc-symbolic-mode nil)
  1546. X     (iters 0)
  1547. X     (m (1- (length p)))
  1548. X     (try-newt (not polish))
  1549. X     (tried-newt nil)
  1550. X     b d f x1 dx dxold)
  1551. X    (while
  1552. X    (and (or (< (setq iters (1+ iters)) 50)
  1553. X         (math-reject-arg x "*Laguerre's method failed to converge"))
  1554. X         (let ((err (math-abs-approx (car p)))
  1555. X           (abx (math-abs-approx x))
  1556. X           (pp p))
  1557. X           (setq b (car p)
  1558. X             d 0 f 0)
  1559. X           (while (setq pp (cdr pp))
  1560. X         (setq f (math-add (math-mul x f) d)
  1561. X               d (math-add (math-mul x d) b)
  1562. X               b (math-add (math-mul x b) (car pp))
  1563. X               err (math-add (math-abs-approx b) (math-mul abx err))))
  1564. X           (math-lessp (calcFunc-scf err (- -2 calc-internal-prec))
  1565. X               (math-abs-approx b)))
  1566. X         (or (not (math-zerop d))
  1567. X         (not (math-zerop f))
  1568. X         (progn
  1569. X           (setq x (math-pow (math-neg b) (list 'frac 1 m)))
  1570. X           nil))
  1571. X         (let* ((g (math-div d b))
  1572. X            (g2 (math-sqr g))
  1573. X            (h (math-sub g2 (math-mul 2 (math-div f b))))
  1574. X            (sq (math-sqrt
  1575. X             (math-mul (1- m) (math-sub (math-mul m h) g2))))
  1576. X            (gp (math-add g sq))
  1577. X            (gm (math-sub g sq)))
  1578. X           (if (math-lessp (calcFunc-abssqr gp) (calcFunc-abssqr gm))
  1579. X           (setq gp gm))
  1580. X           (setq dx (math-div m gp)
  1581. X             x1 (math-sub x dx))
  1582. X           (if (and try-newt
  1583. X            (math-lessp (math-abs-approx dx)
  1584. X                    (calcFunc-scf (math-abs-approx x) -3)))
  1585. X           (let ((newt (math-poly-newton-root p x1 7)))
  1586. X             (setq tried-newt t
  1587. X               try-newt nil)
  1588. X             (if (math-zerop (cdr newt))
  1589. X             (setq x (car newt) x1 x)
  1590. X               (if (math-lessp (cdr newt) '(float 1 -6))
  1591. X               (let ((newt2 (math-poly-newton-root
  1592. X                     p (car newt) 20)))
  1593. X                 (if (math-zerop (cdr newt2))
  1594. X                 (setq x (car newt2) x1 x)
  1595. X                   (setq x (car newt))))))))
  1596. X           (not (or (eq x x1)
  1597. X            (math-nearly-equal x x1))))
  1598. X         (let ((cdx (math-abs-approx dx)))
  1599. X           (setq x x1
  1600. X             tried-newt nil)
  1601. X           (prog1
  1602. X           (or (<= iters 6)
  1603. X               (math-lessp cdx dxold)
  1604. X               (progn
  1605. X             (if polish
  1606. X                 (let ((digs (calcFunc-xpon
  1607. X                      (math-div (math-abs-approx x) cdx))))
  1608. X                   (calc-record-why
  1609. X                "*Could not attain full precision")
  1610. X                   (if (natnump digs)
  1611. X                   (let ((calc-internal-prec (max 3 digs)))
  1612. X                     (setq x (math-normalize x))))))
  1613. X             nil))
  1614. X         (setq dxold cdx)))
  1615. X         (or polish
  1616. X         (math-lessp (calcFunc-scf (math-abs-approx x)
  1617. X                       (- calc-internal-prec))
  1618. X                 dxold))))
  1619. X    (or (and (math-floatp x)
  1620. X         (math-poly-integer-root x))
  1621. X    x))
  1622. )
  1623. X
  1624. (defun math-solve-above-dummy (x)
  1625. X  (and (not (Math-primp x))
  1626. X       (if (and (equal (nth 1 x) '(var SOLVEDUM SOLVEDUM))
  1627. X        (= (length x) 2))
  1628. X       x
  1629. X     (let ((res nil))
  1630. X       (while (and (setq x (cdr x))
  1631. X               (not (setq res (math-solve-above-dummy (car x))))))
  1632. X       res)))
  1633. )
  1634. X
  1635. (defun math-solve-find-root-term (x neg)    ; sets "t2", "t3"
  1636. X  (if (math-solve-find-root-in-prod x)
  1637. X      (setq t3 neg
  1638. X        t1 x)
  1639. X    (and (memq (car-safe x) '(+ -))
  1640. X     (or (math-solve-find-root-term (nth 1 x) neg)
  1641. X         (math-solve-find-root-term (nth 2 x)
  1642. X                    (if (eq (car x) '-) (not neg) neg)))))
  1643. )
  1644. X
  1645. (defun math-solve-find-root-in-prod (x)
  1646. X  (and (consp x)
  1647. X       (math-expr-contains x solve-var)
  1648. X       (or (and (eq (car x) 'calcFunc-sqrt)
  1649. X        (setq t2 2))
  1650. X       (and (eq (car x) '^)
  1651. X        (or (and (memq (math-quarter-integer (nth 2 x)) '(1 2 3))
  1652. X             (setq t2 2))
  1653. X            (and (eq (car-safe (nth 2 x)) 'frac)
  1654. X             (eq (nth 2 (nth 2 x)) 3)
  1655. X             (setq t2 3))))
  1656. X       (and (memq (car x) '(* /))
  1657. X        (or (and (not (math-expr-contains (nth 1 x) solve-var))
  1658. X             (math-solve-find-root-in-prod (nth 2 x)))
  1659. X            (and (not (math-expr-contains (nth 2 x) solve-var))
  1660. X             (math-solve-find-root-in-prod (nth 1 x)))))))
  1661. )
  1662. X
  1663. X
  1664. (defun math-solve-system (exprs solve-vars solve-full)
  1665. X  (setq exprs (mapcar 'list (if (Math-vectorp exprs)
  1666. X                (cdr exprs)
  1667. X                  (list exprs)))
  1668. X    solve-vars (if (Math-vectorp solve-vars)
  1669. X               (cdr solve-vars)
  1670. X             (list solve-vars)))
  1671. X  (or (let ((math-solve-simplifying nil))
  1672. X    (math-solve-system-rec exprs solve-vars nil))
  1673. X      (let ((math-solve-simplifying t))
  1674. X    (math-solve-system-rec exprs solve-vars nil)))
  1675. )
  1676. X
  1677. ;;; The following backtracking solver works by choosing a variable
  1678. ;;; and equation, and trying to solve the equation for the variable.
  1679. ;;; If it succeeds it calls itself recursively with that variable and
  1680. ;;; equation removed from their respective lists, and with the solution
  1681. ;;; added to solns as well as being substituted into all existing
  1682. ;;; equations.  The algorithm terminates when any solution path
  1683. ;;; manages to remove all the variables from var-list.
  1684. X
  1685. ;;; To support calcFunc-roots, entries in eqn-list and solns are
  1686. ;;; actually lists of equations.
  1687. X
  1688. (defun math-solve-system-rec (eqn-list var-list solns)
  1689. X  (if var-list
  1690. X      (let ((v var-list)
  1691. X        (res nil))
  1692. X
  1693. X    ;; Try each variable in turn.
  1694. X    (while
  1695. X        (and
  1696. X         v
  1697. X         (let* ((vv (car v))
  1698. X            (e eqn-list)
  1699. X            (elim (eq (car-safe vv) 'calcFunc-elim)))
  1700. X           (if elim
  1701. X           (setq vv (nth 1 vv)))
  1702. X
  1703. X           ;; Try each equation in turn.
  1704. X           (while
  1705. X           (and
  1706. X            e
  1707. X            (let ((e2 (car e))
  1708. X              (eprev nil)
  1709. X              res2)
  1710. X              (setq res nil)
  1711. X
  1712. X              ;; Try to solve for vv the list of equations e2.
  1713. X              (while (and e2
  1714. X                  (setq res2 (or (and (eq (car e2) eprev)
  1715. X                              res2)
  1716. X                         (math-solve-for (car e2) 0 vv
  1717. X                                 solve-full))))
  1718. X            (setq eprev (car e2)
  1719. X                  res (cons (if (eq solve-full 'all)
  1720. X                        (cdr res2)
  1721. X                      (list res2))
  1722. X                    res)
  1723. X                  e2 (cdr e2)))
  1724. X              (if e2
  1725. X              (setq res nil)
  1726. X
  1727. X            ;; Found a solution.  Now try other variables.
  1728. X            (setq res (nreverse res)
  1729. X                  res (math-solve-system-rec
  1730. X                   (mapcar
  1731. X                    'math-solve-system-subst
  1732. X                    (delq (car e)
  1733. X                      (copy-sequence eqn-list)))
  1734. X                   (delq (car v) (copy-sequence var-list))
  1735. X                   (let ((math-solve-simplifying nil)
  1736. X                     (s (mapcar
  1737. X                         (function
  1738. X                          (lambda (x)
  1739. X                        (cons
  1740. X                         (car x)
  1741. X                         (math-solve-system-subst
  1742. X                          (cdr x)))))
  1743. X                         solns)))
  1744. X                     (if elim
  1745. X                     s
  1746. X                       (cons (cons vv (apply 'append res))
  1747. X                         s)))))
  1748. X            (not res))))
  1749. X         (setq e (cdr e)))
  1750. X           (not res)))
  1751. X      (setq v (cdr v)))
  1752. X    res)
  1753. X
  1754. X    ;; Eliminated all variables, so now put solution into the proper format.
  1755. X    (setq solns (sort solns
  1756. X              (function
  1757. X               (lambda (x y)
  1758. X             (not (memq (car x) (memq (car y) solve-vars)))))))
  1759. X    (if (eq solve-full 'all)
  1760. X    (math-transpose
  1761. X     (math-normalize
  1762. X      (cons 'vec
  1763. X        (if solns
  1764. X            (mapcar (function (lambda (x) (cons 'vec (cdr x)))) solns)
  1765. X          (mapcar (function (lambda (x) (cons 'vec x))) eqn-list)))))
  1766. X      (math-normalize
  1767. X       (cons 'vec 
  1768. X         (if solns
  1769. SHAR_EOF
  1770. true || echo 'restore of calc-alg-2.el failed'
  1771. fi
  1772. echo 'End of  part 5'
  1773. echo 'File calc-alg-2.el is continued in part 6'
  1774. echo 6 > _shar_seq_.tmp
  1775. exit 0
  1776. exit 0 # Just in case...
  1777. -- 
  1778. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1779. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1780. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1781. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1782.